
#include "member_BMotion.h"

using namespace BWE;

double GetValueAt_Linear(double t)
{
	return t;
}
double GetValueAt_OutBounce(double t)
{
	if ((t) < (1 / 2.75))
	{
		return 7.5625 * t * t;
	}
	else if (t < (2 / 2.75))
	{
		t = t - (1.5 / 2.75);
		return 7.5625* t * t + .75;
	}
	else if (t < (2.5 / 2.75))
	{
		t = t - (2.25 / 2.75);
		return 7.5625 * t * t + .9375;
	}
	else
	{
		t = t - (2.625 / 2.75);
		return 7.5625* t * t + .984375;
	}
}
double GetValueAt_InBounce(double t)
{
	double result = GetValueAt_OutBounce(1 - t);
	return 1 - result;
}
double GetValueAt_InOutBounce(double t)
{
	if (t < 0.5)
	{
		double result = GetValueAt_InBounce(t * 2);
		return result * 0.5;
	}
	double result = GetValueAt_OutBounce(t * 2 - 1);
	return result * 0.5 + 0.5;
}
double GetValueAt_OutQuad(double t)
{
	return -(t * (t - 2.0));
}
double GetValueAt_InQuad(double t)
{
	return t*t;
}
double GetValueAt_InOutQuad(double t)
{
	t *= 2.0;
	if (t < 1.0)
		return 0.5 * t * t;
	else
	{
		t -= 1.0;
		return -0.5 * (t * (t - 2) - 1);
	}
}
double GetValueAt_OutCubic(double t)
{
	t = t - 1.0;
	return t*t*t + 1;
}
double GetValueAt_InCubic(double t)
{
	return t*t*t;
}
double GetValueAt_InOutCubic(double t)
{
	t *= 2.0;
	if (t < 1.0)
		return 0.5f * t * t * t;
	else {
		t -= 2.0;
		return 0.5 * (t * t * t + 2.0);
	}
}
double GetValueAt_InQuart(double t)
{
	return t*t*t*t*t;
}
double GetValueAt_OutQuart(double t)
{
	t = t - 1; return -(t*t*t*t - 1);
}
double GetValueAt_InOutQuart(double t)
{
	t = t * 2.0;
	if (t < 1)
		return 0.5*t*t*t*t;
	else
	{
		t -= 2.0;
		return -0.5 * (t*t*t*t - 2);
	}
}
double GetValueAt_OutElastic(double t)
{
	return pow(2.0, -10.0 * t) * sin((t - 0.3 / 4.0) * (2.0 * PI) / 0.3) + 1.0;
}
double GetValueAt_InElastic(double t)
{
	double result = GetValueAt_OutElastic(1.0 - t);
	return 1.0 - result;
}
double GetValueAt_InOutElastic(double t)
{
	t *= 2.0;
	if (t < 1.0)
	{
		t -= 1.0;
		return -0.5 * (1.0 * pow(2.0, 10.0 * t) * sin((t - 0.45f / 4.0) * (2.0 * PI) / 0.45));
	}
	else
	{
		t -= 1.0;
		return pow(2.0, -10.0 * t) * sin((t - 0.45 / 4.0) * (2.0 * PI) / 0.45f) * 0.5 + 1.0;
	}
}
double GetValueAt_OutSine(double t)
{
	return sin(t * (PI / 2.0));
}
double GetValueAt_InSine(double t)
{
	return -cos(t * (PI / 2.0)) + 1.0;
}
double GetValueAt_InOutSine(double t)
{
	return -0.5 * (cos((PI * t)) - 1.0);
}
double GetValueAt_OutBack(double t)
{
	t -= 1.0;
	return t * t * ((1.70158 + 1.0) * t + 1.70158) + 1.0;
}
double GetValueAt_InBack(double t)
{
	return t * t * ((1.70158 + 1.0) * t - 1.70158);
}
double GetValueAt_InOutBack(double t)
{
	double s = 1.70158 * 1.525;
	t *= 2.0;
	if (t < 1.0)
	{
		return 0.5 * (t * t * ((s + 1.0) * t - s));
	}
	else
	{
		double p = t -= 2.0;
		return 0.5 * ((p)* t * ((s + 1.0) * t + s) + 2.0);
	}
}
double GetValueAt_OutCirc(double t)
{
	t -= 1.0;
	return sqrt(1.0 - t * t);
}
double GetValueAt_InCirc(double t)
{
	return -(sqrt(1.0 - (t * t)) - 1.0);
}
double GetValueAt_InOutCirc(double t)
{
	t *= 2.0;
	if (t < 1.0)
	{
		return -0.5f * (sqrt(1.0 - t * t) - 1.0);
	}
	else
	{
		t -= 2.0;
		return 0.5f * (sqrt(1 - t * t) + 1.0);
	}
}
double GetValueAt_OutExpo(double t)
{
	if (t == 1.0)
	{
		return 0.0;
	}
	else
	{
		return -pow(2.0, -10.0 * t) + 1.0;
	}
}
double GetValueAt_InExpo(double t)
{
	if (t == 0.0)
	{
		return 0.0;
	}
	else
	{
		return pow(2.0, 10.0 * (t - 1.0));
	}
}
double GetValueAt_InOutExpo(double t)
{
	if (t == 0.0 || t == 1.0)
	{
		return 0.0;
	}
	else
	{
		t *= 2.0;
		if (t < 1.0)
		{
			return 0.5 * pow(2.0, 10.0 * (t - 1.0));
		}
		else
		{
			return 0.5 * (-pow(2.0, -10.0 * (t - 1.0)) + 2.0);
		}
	}
}

void MotionFunctionInitialize()
{
	static bool initialized = false;
	static GetValueAt_Func funcs[18];
	if (initialized)
		return;
	funcs[Motion_None] = 0;
	funcs[Motion_Linear]		= GetValueAt_Linear;
	funcs[Motion_OutBounce]		= GetValueAt_OutBounce;
	funcs[Motion_InBounce]		= GetValueAt_InBounce;
	funcs[Motion_InOutBounce]	= GetValueAt_InOutBounce;
	funcs[Motion_OutQuad]		= GetValueAt_OutQuad;
	funcs[Motion_InQuad]		= GetValueAt_InQuad;
	funcs[Motion_InOutQuad]		= GetValueAt_InOutQuad;
	funcs[Motion_OutCubic]		= GetValueAt_OutCubic;
	funcs[Motion_InCubic]		= GetValueAt_InCubic;
	funcs[Motion_InOutCubic]	= GetValueAt_InOutCubic;
	funcs[Motion_InQuart]		= GetValueAt_InQuart;
	funcs[Motion_OutQuart]		= GetValueAt_OutQuart;
	funcs[Motion_InOutQuart]	= GetValueAt_InOutQuart;
	funcs[Motion_OutElastic]	= GetValueAt_OutElastic;
	funcs[Motion_InElastic]		= GetValueAt_InElastic;
	funcs[Motion_InOutElastic]	= GetValueAt_InOutElastic;
	funcs[Motion_OutSine]		= GetValueAt_OutSine;
	funcs[Motion_InSine]		= GetValueAt_InSine;
	funcs[Motion_InOutSine]		= GetValueAt_InOutSine;
	funcs[Motion_OutBack]		= GetValueAt_OutBack;
	funcs[Motion_InBack]		= GetValueAt_InBack;
	funcs[Motion_InOutBack]		= GetValueAt_InOutBack;
	funcs[Motion_OutCirc]		= GetValueAt_OutCirc;
	funcs[Motion_InCirc]		= GetValueAt_InCirc;
	funcs[Motion_InOutCirc]		= GetValueAt_InOutCirc;
	funcs[Motion_OutExpo]		= GetValueAt_OutExpo;
	funcs[Motion_InExpo]		= GetValueAt_InExpo;
	funcs[Motion_InOutExpo]		= GetValueAt_InOutExpo;
	initialized = true;
}

member_BMotion::member_BMotion(BMotion* motion)
{
	boss = motion;
	started = false;
	loop = false;
	type = Motion_None;
	func = 0;
	time = 0;
	unit = 1;
	startValue = 0;
	value = 0;
	duration = 1;
	MotionFunctionInitialize();
}
member_BMotion::~member_BMotion()
{

}

static bool initialized = false;
void member_BMotion::freshFunction()
{
	static GetValueAt_Func funcs[Motion_Max];
	if (!initialized)
	{
		funcs[Motion_None] = 0;
		funcs[Motion_OutBounce] = GetValueAt_OutBounce;
		funcs[Motion_InBounce] = GetValueAt_InBounce;
		funcs[Motion_InOutBounce] = GetValueAt_InOutBounce;
		funcs[Motion_Linear] = GetValueAt_Linear;
		funcs[Motion_OutQuad] = GetValueAt_OutQuad;
		funcs[Motion_InQuad] = GetValueAt_InQuad;
		funcs[Motion_InOutQuad] = GetValueAt_InOutQuad;
		funcs[Motion_OutCubic] = GetValueAt_OutCubic;
		funcs[Motion_InCubic] = GetValueAt_InCubic;
		funcs[Motion_InOutCubic] = GetValueAt_InOutCubic;
		funcs[Motion_InQuart] = GetValueAt_InQuart;
		funcs[Motion_OutQuart] = GetValueAt_OutQuart;
		funcs[Motion_InOutQuart] = GetValueAt_InOutQuart;
		funcs[Motion_OutElastic] = GetValueAt_OutElastic;
		funcs[Motion_InElastic] = GetValueAt_InElastic;
		funcs[Motion_InOutElastic] = GetValueAt_InOutElastic;
		funcs[Motion_OutSine] = GetValueAt_OutSine;
		funcs[Motion_InSine] = GetValueAt_InSine;
		funcs[Motion_InOutSine] = GetValueAt_InOutSine;
		funcs[Motion_OutBack] = GetValueAt_OutBack;
		funcs[Motion_InBack] = GetValueAt_InBack;
		funcs[Motion_InOutBack] = GetValueAt_InOutBack;
		funcs[Motion_OutCirc] = GetValueAt_OutCirc;
		funcs[Motion_InCirc] = GetValueAt_InCirc;
		funcs[Motion_InOutCirc] = GetValueAt_InOutCirc;
		funcs[Motion_OutExpo] = GetValueAt_OutExpo;
		funcs[Motion_InExpo] = GetValueAt_InExpo;
		funcs[Motion_InOutExpo] = GetValueAt_InOutExpo;
		initialized = true;
	}
	if (Motion_None < type && type < Motion_Max)
	{
		func = funcs[type];
	}
	else
	{
		func = 0;
	}
}
